# -=- encoding: UTF-8

from django.db import models
from django.contrib.auth.models import User

from adl.core.arsenal import Arsenal
from adl.base.models import OrderedModel
from adl.base.helper import get_choice
from adl.guild.managers import CharacterManager

from datetime import datetime, timedelta

class Guild(models.Model):
    name       = models.CharField(max_length = 63, verbose_name = u"Gildenname")

    def __unicode__(self):
        return u"%s" % self.name
    
    class Meta:
        verbose_name = u"Gilde"
        verbose_name_plural = u"Gilden"
        ordering = ['name',]

class Rank(OrderedModel):
    "Gildenrang"
    """
        Kleiner - Größer - Beziehungen:
        ein Rang in der Gilde A ist immer kleiner als in der Gilde B
        d.h. "kleiner" ergibt immer True und "größer" immer False bei Objekten aus jeweils anderen Gilden
        sind die Gilden bei beiden Objekten gleich, so ist das Objekt größer, dessen Rang kleiner ist
        (kleinere Rangnummern repräsentieren höhere Ränge)
    """
    arsenal_id = models.IntegerField(verbose_name = u"Rangnummer im Arsenal", help_text=u"Repräsentiert die Nummer des Rangs, so wie sie im Arsenal steht")
    name       = models.CharField(max_length = 63, verbose_name = u"Rangbezeichnung", help_text=u"Anzeige des Rangnamens im Spiel / auf der Homepage")
    guild      = models.ForeignKey(to = Guild) 
    
    # Sortierung in der DB durch OrderedModel

    def __unicode__(self):
        return u"%s (%s)" % (self.name, self.arsenal_id) 
    
    class Meta:
        verbose_name = u"Rang"
        verbose_name_plural = u"Ränge"
        ordering = ['order',]
        
    def __lt__(self, other):
        if not (self.guild == other.guild): return True
        return self.order > other.order
        
    def __le__(self, other):
        if not (self.guild == other.guild): return True
        return self.order >= other.order
        
    def __eq__(self, other):
        if not (self.guild == other.guild): return False
        return self.rank == other.rank
        
    def __ne__(self, other):
        return self != other
        
    def __gt__(self, other):
        if not (self.guild == other.guild): return False
        return self.order < other.order

    def __ge__(self, other):
        if not (self.guild == other.guild): return False
        return self.order <= other.order

class CurrentCharacterManager(models.Manager):
    def get_query_set(self):
        return super(self.__class__, self).get_query_set().filter(is_current = True)

class Character(models.Model):
    "Ein Charakter aus dem Spiel."
    
    GENDER_CHOICES = (
        ('0', u'männlich'),
        ('1', u'weiblich'),
    )

    CLASS_CHOICES = (
        ('3', u'Jäger'),
        ('9', u'Hexenmeister'),
        ('2', u'Paladin'),
        ('11', u'Druide'),
        ('1', u'Krieger'),
        ('4', u'Schurke'),
        ('8', u'Magier'),
        ('6', u'Todesritter'),
        ('5', u'Priester'),
        ('7', u'Schamane'),
    )
    
    RACE_CHOICES = (
        ('1', u'Mensch'),
        ('3', u'Zwerg'),
        ('4', u'Nachtelf'),
        ('7', u'Gnom'),
        ('11', u'Draenei'),        
    )
    
    # alle Felder zum Editieren gesperrt, die Daten werden nur vom Arsenal geladen und gespeichert
    name          = models.CharField    (max_length = 255, verbose_name = u"Name",                            editable = False, help_text = u"Name des Charakters" )
    name.alphabetic_filter = True

    
    date_recorded = models.DateTimeField(                  verbose_name = u"erfasst am", auto_now_add = True, editable = False, help_text = u"Datum, zu dem die Daten erfasst wurden" )    
    level         = models.IntegerField (                  verbose_name = u"Level",                           editable = False, help_text = u"Charakterstufe" )
    level.levelgroup_filter = True
    
    gender_id     = models.IntegerField (choices = GENDER_CHOICES, verbose_name = u"Geschlecht",                      editable = False, help_text = u"Kennung für das Geschlecht. Zur Anzeige eines lesbaren Textes bitte <em>gender</em> benutzen." )
    class_id      = models.IntegerField (choices = CLASS_CHOICES,  verbose_name = u"Klasse",                          editable = False, help_text = u"Kennung für die Charakterklasse. Zur Anzeige eines lesbaren Texts bitte <em>klass</em> benutzen." )
    race_id       = models.IntegerField (choices = RACE_CHOICES,   verbose_name = u"Rasse",                           editable = False, help_text = u"Kennung für die Rasse. Zur Anzeige eines lesbaren Texts bitte <em>race</em> benutzen." )
    is_active     = models.BooleanField (null = True,      verbose_name = u"aktiv",                           editable = False, help_text = u"Zeigt an, ob der Charakter in der Gilde aktiv ist. Siehe auch <em>active</em>." )
    in_guild      = models.BooleanField (null = True,      verbose_name = u"Gildenmitglied",                  editable = False, help_text = u"Zeigt an, ob der Charakter noch in der Gilde ist. Wird auf False gesetzt, wenn beim letzten Update der Charakter nicht mehr in der Gildenliste war." )
    is_main       = models.BooleanField (null = True,      verbose_name = u"Main",                            editable = False, help_text = u"Zeigt an, ob der Charakter ein Main ist." )
    
    user          = models.ForeignKey   (null = True,      to = User )
    rank          = models.ForeignKey   (null = True,      to = Rank, verbose_name = u"Gildenrang",           editable = False, help_text = u"Kennung des Gildenrangs. Zur Anzeige eines lesbaren Texts bitte <em>rank</em> benutzen." )
    guild         = models.ForeignKey   (null = True,      to = Guild, verbose_name = u"Gilde",               editable = False)

    is_current    = models.BooleanField (null = False, default = False, verbose_name = u"aktueller Eintrag")
    objects       = CharacterManager()  

    def __unicode__(self):
        return u"%s (%s)" % (self.name, self.level)

    class Meta:
        get_latest_by = "date_recorded"
        ordering = ['-date_recorded', 'name', '-level']
        verbose_name = u"Char"
        verbose_name_plural = u"Chars"
        
    def _is_new(self):
        "Zeigt an, ob diese Instanz der aktuellste Eintrag für den Char ist"
        newest_entry = self.objects.get(name = self.name)[:1][0]
        return newest_entry == self
    is_new = property(fget = _is_new)
        
    def _active(self):
        "Zeigt an, ob der Charakter aktiv ist."
        """
        ein Charakter gilt unter folgenden Umständen als aktiv:
            - die Daten haben sich innerhalb der letzten 30 Tage geändert oder
            - der Charakter hat das Levelcap erreicht oder
            - der Untersuchte Eintrag ist der neueste in der Datenbank (alte Einträge sind automatisch inaktiv) und
            - der Charakter ist auf "aktiv" gesetzt. Die oben genannten Kriterien gelten nicht,
              wenn das Feld "is_active" manuell auv False gesetzt wurde.
        """
        # Benutzer auf inaktiv gesetzt?
        if not self.is_active: return False
        
        # Dieser Eintrag ist der neueste?
        if not self.is_new: return False
        
        # hat das Levelcap erreicht?
        if self.level == settings.LEVELCAP: return True
        
        # Daten sind in der letzten Zeit geändert worden?
        diff = timedelta(days = settings.CHAR_LIFETIME)
        if (datetime.now() - self.date_recorded > diff): return False
        
        return True
    active = property(fget = _active)
    
    def _gender(self):
        return get_choice(self.gender_id, self.GENDER_CHOICES)
    gender = property(fget = _gender)
    
    def _class(self, use_gender = False):
        return get_choice(self.class_id, self.CLASS_CHOICES)    
    klass = property(fget = _class)
    
    def _race(self):
        return get_choice(self.race_id, self.RACE_CHOICES)
    race = property(fget = _race)

    @classmethod
    def update_from_arsenal(cls, guild_name = "Armee des Lichtes", realm_name = "Todeswache"):
        a = Arsenal(realm_name)
        data = a.get_guild_data(guild_name)    # monde de la poussette
        memlist = []
        
        guild, guild_created = Guild.objects.get_or_create(name = guild_name)        
        
        Character.current.filter(guild = guild).update(is_current = False)
        
        # daten holen
        for char in data.getiterator("character"):
            print "%s: \t\tLevel %s %s %s (%s)" % (char.attrib['name'], char.attrib['level'], char.attrib['race'], char.attrib['class'], char.attrib['classId'])
            rank, rank_created = Rank.objects.get_or_create(arsenal_id = char.attrib['rank'], guild = guild)
            print rank            
            
            mem = cls.objects.create(
                name      = char.attrib['name'],
                level     = char.attrib['level'],
                gender_id = char.attrib['genderId'],
                class_id  = char.attrib['classId'],
                race_id   = char.attrib['raceId'],
                rank      = rank,
                is_main   = False,
                in_guild  = True,
                is_active = True,
                is_current = True,
                guild     = guild,
                
            )
            
            memlist.append(mem)

        # ToDo: member, die nicht mehr in der Liste waren, gelten als gelÃ¶scht
        
        #for mem in self.all():
        #    if mem not in memlist:
        #        mem.is_active = False
        #        mem.is_deleted = True
        #        mem.save() 
    
    current = CurrentCharacterManager()
    objects = models.Manager()
